#include <iostream>
#include <string>
#include <map>
#include <functional>
#include <sstream>
#include <windows.h>
#include <filesystem>
#include <sqlite3.h>
// 定义命令处理函数类型
void parentFunction();

using CommandHandler = std::function<void()>;
namespace fs = std::filesystem;
// 命令处理函数示例
void helpCommand() {
    std::cout << "可用命令：" << std::endl;
    std::cout << "  help - 显示帮助信息" << std::endl;
    std::cout << "  greet - 打招呼" << std::endl;
    std::cout << "  exit - 退出程序" << std::endl;
}

void greetCommand() {
    std::string name;
    std::cout << "请输入你的名字: ";
    std::getline(std::cin, name);
    std::cout << "你好, " << name << "!" << std::endl;
}

void returnCommand() {
    std::cout << "返回上一级菜单。" << std::endl;
    // 这里可以实现返回上一级菜单的功能
    return;
}

// 复制文件或目录的函数
void copy(const fs::path& source, const fs::path& destination) {
    try {
        fs::copy(source, destination, fs::copy_options::recursive);
        std::cout << "复制成功: " << source << " 到 " << destination << std::endl;
    } catch (const fs::filesystem_error& e) {
        std::cerr << "复制失败: " << e.what() << std::endl;
    }
}

void exitCommand() {
    std::cout << "程序退出。" << std::endl;

    exit(0);
}

std::vector<std::string> splitString(const std::string& str, char delimiter) {
    std::vector<std::string> tokens;
    std::stringstream ss(str);
    std::string token;
    while (std::getline(ss, token, delimiter)) {
        tokens.push_back(token);
    }
    return tokens;
}


// 根据端口结束进程
void killProcessByPort(int port) {
    // 使用 netstat 命令查找占用端口的进程ID
    std::string command = "netstat -ano | findstr :" + std::to_string(port);
    FILE* pipe = _popen(command.c_str(), "r");
    if (!pipe) {
        std::cerr << "无法执行命令" << std::endl;
        return;
    }

    char buffer[128];
    std::string result = "";
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr) {
        result += buffer;
    }
    _pclose(pipe);

    // 解析进程ID
    size_t pos = result.find_last_of(' ');
    if (pos == std::string::npos) {
        std::cerr << "未找到占用端口 " << port << " 的进程" << std::endl;
        return;
    }

    std::string pidStr = result.substr(pos + 1);
    int pid = std::stoi(pidStr);

    // 使用 taskkill 命令结束进程
    std::string killCommand = "taskkill /PID " + std::to_string(pid) + " /F";
    int resultCode = system(killCommand.c_str());
    if (resultCode != 0) {
        std::cerr << "结束进程失败,请检查权限。" << std::endl;
        return;
    }
    std::cout << "端口: " << port << "进程: " << pid << " 已结束。" << std::endl;
    std::cout << "返回主菜单。" << std::endl;
    parentFunction();
}

// 根据端口结束进程
void endProcessByPort(){
    std::cout << "请输入端口号,请输入端口,多个请用逗号隔开" << std::endl;
    std::cout << "exit: 返回上一级菜单。" << std::endl;
    std::string port;
    std::getline(std::cin, port);
    if(port == "exit"){
        std::cout << "返回上一级菜单。" << std::endl;
        parentFunction();
        return;
    }
    char delimiter = ',';
    std::vector<std::string> result = splitString(port, delimiter);

    for (const std::string& token : result) {
        std::cout << token << std::endl;
        try {
            int portNumber = std::stoi(token); // 将字符串转换为整数
            std::cout << "端口号: " << portNumber << std::endl;
            // 调用 killProcessByPort(portNumber) 结束进程
            killProcessByPort(portNumber);
        } catch (const std::invalid_argument& e) {
            std::cerr << "无效的端口号: " << token << std::endl;
        } catch (const std::out_of_range& e) {
            std::cerr << "端口号超出范围: " << token << std::endl;
        }
    }
}

// 父菜单函数
void parentFunction(){
    // 定义命令映射表
    std::map<std::string, CommandHandler> commands = {
            {"help", helpCommand},
            {"greet", greetCommand},
            {"1", endProcessByPort},
            {"exit", exitCommand}
    };

    std::cout << "欢迎使用命令行工具集！" << std::endl;
    std::cout << "1:    根据端口结束对应进程,多个端口用逗号隔开！" << std::endl;
    std::cout << "exit: 退出程序" << std::endl;


    while (true) {
        std::string input;
        std::cout << "> "; // 提示符
        std::getline(std::cin, input);

        // 查找并执行命令
        auto it = commands.find(input);
        if (it != commands.end()) {
            it->second(); // 调用对应的命令处理函数
        } else {
            std::cout << "未知命令。输入 'help' 查看可用命令。" << std::endl;
        }
    }
}

int main() {
    SetConsoleOutputCP(CP_UTF8);
    parentFunction();

    return 0;
}
